// wglwindow.cpp
//

#include "config.h"

#include "wgl/wglwindow.hpp"
#include "wgl/wgl_gl.hpp"

using namespace wgl;



// [TEMP]
#define WGL_GL_VERSION_MAJOR 3
#define WGL_GL_VERSION_MINOR 3

// set to true to disable deprecated functions
#define WGL_GL_CONTEXT_FORWARD_COMPATIBLE false

// CORE | COMPATIBILITY | ES
#define WGL_GL_CONTEXT_PROFILE SDL_GL_CONTEXT_PROFILE_COMPATIBILITY



#define DOUBLE_BUFFER 1
#define DEPTH_SIZE 16



// Window::Window
//
Window::Window ( const WindowSettings &settings,
                 bool show )
  : settings(settings)
{
  if (show)
    this->show();
}



// Window::Window
//
Window::Window ( int requested_width,
                 int requested_height,
                 bool show )
  : Window(WindowSettings
           {
             requested_width,
             requested_height,
             false, // fullscreen
             false, // fullscreen_desktpo
             true
           }, // vsync
           show)
{
}



// Window::~Window
//
Window::~Window ()
{
  hide();
}



// Window::get_sdl_window_id
//
Uint32 Window::get_sdl_window_id () const
{
  if (sdl_window)
    {
      Uint32 id = SDL_GetWindowID(sdl_window);
      if (!id)
        WGL_FATAL("could not get sdl_window id: %s", SDL_GetError());
      return id;
    }
  else
    {
      return 0;
    }
}



// Window::show
//
bool Window::show ()
{
  if (sdl_window)
    return true;

  int context_flags =  0;
  if (WGL_GL_CONTEXT_FORWARD_COMPATIBLE)
    context_flags |= SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;

  Uint32 flags = SDL_WINDOW_OPENGL;
  int width = settings.width;
  int height = settings.height;

  if (settings.desktop_fullscreen)
    {
      SDL_DisplayMode mode;
      if (SDL_GetDesktopDisplayMode(0, &mode) != 0)
        WGL_FATAL("could not get desktop display mode: %s", SDL_GetError());
      WGL_TRACE("desktop display mode: %dx%d (%dHz)", mode.w, mode.h,mode.refresh_rate);
      width = mode.w;
      height = mode.h;
      flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
    }
  else if (settings.fullscreen)
    {
      flags |= SDL_WINDOW_FULLSCREEN;
    }
  
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, WGL_GL_CONTEXT_PROFILE);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, WGL_GL_VERSION_MAJOR);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, WGL_GL_VERSION_MINOR);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, DOUBLE_BUFFER);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, DEPTH_SIZE);
  // SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

  if ((sdl_window = SDL_CreateWindow("wgl-app",
                                     SDL_WINDOWPOS_UNDEFINED,
                                     SDL_WINDOWPOS_UNDEFINED,
                                     width,
                                     height,
                                     flags)))
    {
      // [FIXME] should check that created display has the right size
      // or re-process resize
      
      if (!(gl_context = SDL_GL_CreateContext(sdl_window)))
        WGL_FATAL("could not create GL context: %s", SDL_GetError());
      //
      SDL_GL_SetSwapInterval(settings.vsync ? 1 : 0);
      //
      app_layer_master.reset();
      app_layer_master.make_current();
      //
      print_gl_infos();
      return true;
    }
  else
    {
      WGL_FATAL("could not create sdl window: %s", SDL_GetError());
      return false;
    }
}



// Window::print_gl_infos
//
void Window::print_gl_infos ()
{
  int glver_maj, glver_min;

  if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &glver_maj) != 0 ||
      SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &glver_min) != 0)
    {
      WGL_FATAL("could not get OpenGL version: %s", SDL_GetError());
    }
  WGL_TRACE("OpenGL version: %d.%d", glver_maj, glver_min);

  GLint max_attribs;
  gl.GetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attribs);
  WGL_TRACE("max vertex attributes: %d", max_attribs);
}



// Window::hide
//
void Window::hide ()
{
  if (!sdl_window)
    return;

  SDL_GL_DeleteContext(gl_context);
  gl_context = nullptr;
  SDL_DestroyWindow(sdl_window);
  sdl_window = nullptr;
}



// Window::make_current
//
void Window::make_current ()
{
  if (SDL_GL_MakeCurrent(sdl_window, gl_context) != 0)
    WGL_FATAL("could not make GL context current: %s", SDL_GetError());
  app_layer_master.make_current();
}



// Window::swap_display
//
void Window::swap_display ()
{
  SDL_GL_SwapWindow(sdl_window);
}
